import React,{ useState, useEffect } from 'react'
import axios from 'axios'
// 引入 antd 组件库组件
import { Table,Tag,Button,Modal,Popover,Switch } from 'antd'
// 引入 antd 组件图标
import { DeleteOutlined,EditOutlined,ExclamationCircleOutlined } from '@ant-design/icons'
const { confirm } = Modal

export default function RightList() {

  // 定义一个变量用于存储表格数据
  const [dataSource, setdataSource] = useState([])

  /* 
    useEffect钩子中的第一次参数是一个函数，它会在组件渲染完成后执行，第二个参数用于设置依赖项列表(当依赖项发生变化时，才会重新执行回调函数)
    这里的依赖项列表是一个空数组，所以这个useEffect只会在组件初始化时执行一次
  */
  useEffect(()=>{
    // axios 请求成功后会返回一个成功的Promise，并且将请求成功返回的数据作为参数传递给then方法的第一个箭头函数，如果请求失败，就会将失败结果传递给then方法中的第二个箭头函数(这里没有将第二个箭头函数写出来)
    axios.get("http://localhost:5000/rights?_embed=children").then(res=>{   // res 接收到的是请求成功后返回的数据
      // console.log(res.data);
      const list = res.data
      list.forEach(element => {
        // 遍历请求成功返回的数组数据，如果元素的children的长度为0，那么就将该元素的children赋值为空，这样这个元素放到Table组件中就不会生成下拉表格行了
        if(element.children.length === 0){
          element.children = ""
        }
      });
      setdataSource(list)
    })
  },[])

  // 表单中删除按钮的点击事件回调
  const confirmMethod = (item)=>{
    // 气泡弹出框
    confirm({
      title: '你确定要删除?',
      icon: <ExclamationCircleOutlined />,
      cancelText: "取消",
      onOk() {
        deleteMethod(item)
      },
      onCancel() {

      },
    })
  }
  // 删除按钮确认后的触发的回调
  const deleteMethod = (item)=>{
    console.log(item);
    // 根据元素的grade属性判断该元素对应在表格中的层级(判断它是都是下拉表格中的表格项)
    if(item.grade === 1){ // 如果grade等于1，说明它是一级表格项，不是下拉表格中的表格项
      // 利用 filter 方法在 dataSource 数组中将当前这一行数据对应的元素过滤掉，再将处理后的数组赋值给dataSource
      // 这种方式删除，刷新后可以恢复
      setdataSource(dataSource.filter(data => data.id !== item.id))

      // 调用接口在服务器中根据id删除指定的元素
      // 这种方式删除，刷新后无法恢复，因为这是直接删除后台数据库中的数据，是无法恢复的
      // axios.delete(`http://localhost:5000/rights/${item.id}`)
    }else{
      // 二级表格项元素的rightId值等于它所属的一级表格项元素的id值
      // 如果当前这个元素的grade值为2，说明它是二级表格项，就根据它的rightId值找到它所属的一级表格项
      // console.log(item.rightId);
      // 理由filter过滤找出id值等于当前这个元素的rightId值的元素，它就是当前这个二级表格项所属的一级表格项
      const list = dataSource.filter(data => data.id===item.rightId)
      // 再在这个一级表格项元素中通过filter过滤去除掉当前这个二级表格项元素，从而实现删除二级表格项的操作
      // list是一个数组，数组中的第一个元素装的是当前这个一级表格项元素
      list[0].children = list[0].children.filter(data => data.id!==item.id)
      // console.log(list);
      // 这里的dataSource经过filter的遍历后实际上受到了影响，因为它是浅复制
      setdataSource([...dataSource])
      // 以上这种方式删除，刷新后可以恢复，下面这种发生删除，刷新后无法恢复，因为下面是直接删除后台数据库中的数据，是无法恢复的

      // 调用接口删除指定的二级表格项元素
      // axios.delete(`/children/${item.id}`)
    }
  }

  // Switch开关组件点击后的事件回调函数
  const switchMethod =(item)=>{
    // console.log(item);
    // 如果pagepermisson值为1，那么就赋值为0，如果值不为1，那么就赋值为1
    item.pagepermisson = item.pagepermisson===1?0:1
    // 重新给dataSource赋予新的值，使得页面发生更新
    setdataSource([...dataSource])

    // 上面那种写法给页面的影响在刷新后会消失，因为数据都是从服务器中获取的，只要不直接修改服务器数据，页面就不会受永久性的影响
    // 下面那种写法给页面的影响不会再刷新后销售，因为它是通过接口直接修改服务器中的数据

    if (item.grade === 1) {   // grade用于判断当前表格项元素的层级，1代表一级，2代表二级
      // patch请求方式用于更新服务器中的指定元素
      axios.patch(`http://localhost:5000/rights/${item.id}`, {
        pagepermisson: item.pagepermisson
      })
    } else {
      axios.patch(`http://localhost:5000/children/${item.id}`, {
        pagepermisson: item.pagepermisson
      })
    }
  }

  // antd 提供的写法，有规律，这里如果有不明白就查看 antd 4版本的文档
  const columns = [
    {
      title: 'ID',
      dataIndex: 'id',
      key: 'id',
    },
    {
      title: '权限名称',
      dataIndex: 'label',
      key: 'label',
    },
    {
      title: '权限路径',
      dataIndex: 'key',
      key: 'key',
      // render是给当前这一列中的所有表格都渲染对应的组件标签
      render: (key) => {
        return <Tag color="green">{key}</Tag>
      }
    },
    {
      title: '操作',
      render: (item)=>{   // item 装的是当前这一行对应的元素
        return <div>
          <Button 
            type="danger" 
            shape="circle" 
            icon={<DeleteOutlined/>}
            onClick={()=>{
              return confirmMethod(item)
            }}
            style={{marginRight:"5px"}}
           />
           {/* 气泡卡片组件 */}
           {/* 
              content 是设置气泡卡片的展示的内容
              title 是设置标题
              trigger 是设置气泡卡片触发显示的条件 click 是点击后使得气泡卡片显示
           */}
           <Popover
            content={
              <div style={{textAlign:"center"}}>
                {/* 开关组件 */}
                {/* 
                  checked的值控制着这个开关组件的状态，如果值为true，那么这个开关就处于打开状态，反之则处于关闭状态
                  如果当前这个表格项元素中存在pagepermisson属性，并且值为1，那么就将这个开关打开，如果不存在，就设置为关闭
                */}
                <Switch checked={item.pagepermisson} onChange={()=>{switchMethod(item)}}></Switch>
              </div>
            }
            title="配置项" 
            // 下面代码的意思是：
            // 如果当前这一行表格项元素存在pagepermisson属性(如果侧边栏中有这个表格元素对应的菜单项，那么这个表格元素中就有pagepermisson元素)，
            // 那么就将trigger属性值设置为click，这样就可以通过点击触发这个气泡卡片组件；反之，就将trigger属性值设置为空，这样就无法使得这个气泡卡片组件显示
            trigger={item.pagepermisson === undefined?'':'click'}
            >
              <Button 
                type="primary" 
                shape="circle" 
                icon={<EditOutlined/>} 
                // 如果当前表格项元素不存在pagepermisson属性，那么就禁用这个Button组件
                disabled={item.pagepermisson === undefined} 
              />
           </Popover>
        </div>
      }
    }
  ];
  
  return (
    /* 
      columns 表格列的配置描述(每一列的开头的设置)
      dataSource 数据数组，设置每一行具体的信息
      pagination 给表格添加分页器
          pageSize 设置分页器每一页能够显示的信息条数
    */
    <Table 
      dataSource={dataSource} 
      columns={columns} 
      pagination={{
        pageSize: 5
      }}
     />
  )
}
